package com.colis.quartz.utils;

import com.colis.quartz.common.constant.QuartzConstants;
import com.colis.quartz.component.MyQuartzJob;
import com.colis.quartz.module.sms.QuartzTask;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

/**
 * <p> 描述： </p>
 *
 * @author wlp
 * @version 1.0.0
 * @date 2022/1/14 11:39
 */
@Slf4j
public class SchedulerJobUtil {

    /**
     * <p> 方法描述: </p>
     *
     * @param scheduler  任务调度器
     * @param quartzTask 任务配置
     * @author wlp
     * @date 2022/1/14 11:51
     */
    public static void addJob(Scheduler scheduler, QuartzTask quartzTask) throws SchedulerException {
        try {
            JobDetail jobDetail = getJobDetail(quartzTask);
            CronTrigger cronTrigger = getCronTrigger(quartzTask);
            scheduler.scheduleJob(jobDetail, cronTrigger);
        } catch (Exception e) {
            log.error("加载定时任务异常啦!", e);
            throw new SchedulerException("加载定时任务异常啦!", e);
        }
    }

    /**
     * 立即执行任务
     */
    public static void runJob(Scheduler scheduler, QuartzTask quartzTask) throws SchedulerException {
        try {
            scheduler.triggerJob(getJobKey(quartzTask.getId()));
        } catch (SchedulerException e) {
            log.error("立即执行定时任务失败!", e);
            throw new SchedulerException("立即执行定时任务失败!", e);
        }
    }

    /**
     * <p> 方法描述: 暂停定时任务 </p>
     *
     * @param scheduler 任务调度器
     * @param quartzId  任务id
     * @author wlp
     * @date 2022/1/14 14:07
     */
    public static void pauseJob(Scheduler scheduler, Long quartzId) throws SchedulerException {
        try {
            scheduler.pauseJob(getJobKey(quartzId));
        } catch (SchedulerException e) {
            log.error("暂停定时任务失败啦!", e);
            throw new SchedulerException("暂停定时任务失败啦!", e);
        }
    }

    /**
     * <p> 方法描述: 恢复定时任务 </p>
     *
     * @param scheduler 任务调度器
     * @param quartzId  任务id
     * @author wlp
     * @date 2022/1/14 13:56
     */
    public static void resumeJob(Scheduler scheduler, Long quartzId) throws SchedulerException {
        try {
            scheduler.resumeJob(getJobKey(quartzId));
        } catch (SchedulerException e) {
            log.error("恢复定时任务失败啦！", e);
            throw new SchedulerException("恢复定时任务失败啦！", e);
        }
    }

    /**
     * <p> 方法描述: 重载任务 </p>
     *
     * @param scheduler  任务调度器
     * @param quartzTask 任务配置
     * @author wlp
     * @date 2022/1/14 14:16
     */
    public void reloadJob(Scheduler scheduler, QuartzTask quartzTask) throws SchedulerException {
        try {
            // 获取以前的触发器
            TriggerKey triggerKey = getTriggerKey(quartzTask.getId());
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 删除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除原来的job
            scheduler.deleteJob(getJobKey(quartzTask.getId()));
            JobDetail jobDetail = getJobDetail(quartzTask);
            CronTrigger cronTrigger = getCronTrigger(quartzTask);
            // 重新加载job
            scheduler.scheduleJob(jobDetail, cronTrigger);
        } catch (Exception e) {
            log.error("重载定时任务异常啦!", e);
            throw new SchedulerException("重载定时任务异常啦!", e);
        }
    }

    /**
     * <p> 方法描述: 卸载任务 </p>
     *
     * @param scheduler 任务调度器
     * @param quartzId  任务id
     * @author wlp
     * @date 2022/1/14 14:19
     */
    public void unloadJob(Scheduler scheduler, Long quartzId) throws SchedulerException {
        TriggerKey triggerKey = getTriggerKey(quartzId);
        // 停止触发器
        scheduler.pauseTrigger(triggerKey);
        // 卸载定时任务
        scheduler.unscheduleJob(triggerKey);
        // 删除原来的job
        scheduler.deleteJob(getJobKey(quartzId));
    }

    /**
     * <p> 方法描述: 获取新的JobDetail </p>
     *
     * @param quartzTask 任务配置
     * @return JobDetail 新的JobDetail
     * @author wlp
     * @date 2022/1/14 11:43
     */
    private static JobDetail getJobDetail(QuartzTask quartzTask) {
        JobDetail jobDetail = JobBuilder.newJob()
                .withIdentity(getJobKey(quartzTask.getId()))
                .ofType(MyQuartzJob.class).build();
        jobDetail.getJobDataMap().put(QuartzConstants.QUARTZ_JOB_MAP_KEY, quartzTask);
        return jobDetail;
    }

    /**
     * <p> 方法描述: 获取cron触发器</p>
     *
     * @param quartzTask 任务配置
     * @return CronTrigger 触发器
     * @author wlp
     * @date 2022/1/14 11:46
     */
    private static CronTrigger getCronTrigger(QuartzTask quartzTask) {
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartzTask.getQuartzCron())
                // 不触发立即执行
                // 等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
                .withMisfireHandlingInstructionDoNothing();
        return TriggerBuilder.newTrigger()
                .withIdentity(getTriggerKey(quartzTask.getId()))
                .withSchedule(cronScheduleBuilder)
                .build();
    }

    /**
     * <p> 方法描述: 获取触发器key</p>
     *
     * @param quartzId 任务id
     * @return TriggerKey
     * @author wlp
     * @date 2022/1/14 14:12
     */
    private static TriggerKey getTriggerKey(Long quartzId) {
        return TriggerKey.triggerKey(QuartzConstants.QUARTZ_TRIGGER_KEY + quartzId);
    }

    /**
     * <p> 方法描述: 获取jobkey</p>
     *
     * @param quartzId 任务id
     * @return String
     * @author wlp
     * @date 2022/1/14 13:43
     */
    private static JobKey getJobKey(Long quartzId) {
        return JobKey.jobKey(QuartzConstants.QUARTZ_JOB_KEY + quartzId, QuartzConstants.QUARTZ_JOB_GROUP);
    }
}
